package com.heima.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.util.AppJwtUtil;
import com.heima.common.util.AppThreadLocalUtil;
import com.heima.user.entity.ApAuthor;
import com.heima.user.dto.FollowBehaviorDto;
import com.heima.user.dto.LoginDto;
import com.heima.user.dto.UserRelationDto;
import com.heima.user.entity.ApUser;
import com.heima.user.entity.ApUserFollow;
import com.heima.user.feign.ArticleFeign;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.service.IApUserFollowService;
import com.heima.user.service.IApUserService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * APP用户信息表 服务实现类
 * </p>
 *
 * @author mcm
 * @since 2022-03-11
 */
@EqualsAndHashCode(callSuper = true)
@Service
@Data
@ConfigurationProperties(prefix = "topic")
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements IApUserService {
    @Autowired
    private ArticleFeign articleFeign;
    @Autowired
    private IApUserFollowService followService;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    private String followBehaviorTopic;


    @Override
    /**
     *  //分两种情况，一个是游客登陆，这个时候防止被拦截器拦截要获取设备id,另一种就手机号密码
     */
    public ResponseResult login(LoginDto dto) {
        //如果什么参数都没有，估计是非法渠道进入，直接返回
        if (dto == null || (StringUtils.isEmpty(dto.getPhone()) && StringUtils.isEmpty(dto.getPassword()) && StringUtils.isEmpty(dto.getEquipmentId())))
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        // 判断手机号和密码是否为空 ,都不为空,使用手机号和密码进行登录
        if (!StringUtils.isEmpty(dto.getPassword()) && !StringUtils.isEmpty(dto.getPhone())) {
            // 根据手机号查询
            LambdaQueryWrapper<ApUser> query = new LambdaQueryWrapper<>();
            query.eq(ApUser::getPhone, dto.getPhone());
            ApUser adUser = this.getOne(query);
            // 不存在,提示错误消息
            if (adUser == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
            // 存在,获取盐,使用用户传入的密码+盐 进行md5计算
            String salt = adUser.getSalt();
            String pwdStr = dto.getPassword() + salt;
            String md5Str = DigestUtils.md5DigestAsHex(pwdStr.getBytes());
            // 对比md5值和数据库中存放的密码
            if (!md5Str.equals(adUser.getPassword())) {
                // 不一致,返回密码错误
                return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
            }

            // 一致的话,使用JWT生成token 使用用户id生成
            Map<String, Object> claimMap = new HashMap<>();
            claimMap.put("userId", adUser.getId());
            claimMap.put("userName", adUser.getName());
            String token = AppJwtUtil.getToken(claimMap);

            // 定义返回的结果
            Map<String, Object> map = new HashMap<>();
            // 脱敏处理
            adUser.setPhone(null);
            adUser.setPassword(null);
            adUser.setSalt(null);
            map.put("user", adUser);
            map.put("token", token);
            // 通用的响应
            return ResponseResult.okResult(map);

        }
        //如果设备id不为空，则设为游客登录
        if (!StringUtils.isEmpty(dto.getEquipmentId())) {
            HashMap<String, Object> claimMap = new HashMap<>();
            claimMap.put("userId", 0);
            String token = AppJwtUtil.getToken(claimMap);
            HashMap<String, Object> map = new HashMap<>();
            map.put("token", token);
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }

    @Override
    public ResponseResult follow(UserRelationDto dto) {
        // 当前登录的用户可以从本地线程中查询
        User user = AppThreadLocalUtil.get();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        // 构建关注对象
        ApUserFollow userFollow = new ApUserFollow();
        userFollow.setUserId(user.getUserId());
        ApUser apUser = this.getById(user.getUserId());
        userFollow.setUserName(apUser.getName());

        // 关注的用户可以通过作者去查询
        ApAuthor apAuthor = null;
        ResponseResult<ApAuthor> responseResult = articleFeign.getAuthorById(dto.getAuthorId());
        if (responseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            apAuthor = responseResult.getData();
        }
        if (apAuthor != null) {
            userFollow.setFollowId(apAuthor.getUserId());
            userFollow.setFollowName(apAuthor.getName());
        }
        userFollow.setLevel(0);
        userFollow.setCreatedTime(new Date());
        LambdaQueryWrapper<ApUserFollow> query = new LambdaQueryWrapper<>();
        query.eq(ApUserFollow::getUserId, user.getUserId());
        query.eq(ApUserFollow::getFollowId, apAuthor.getUserId());
        // 判断操作是关注还是取消关注
        if (dto.getOperation() == 0) {
            // 如果是关注,需要保存记录,判断该用户是否已经对这个作者有过关注记录
            ApUserFollow one = followService.getOne(query);
            if (one == null) {
                followService.save(userFollow);
            }
        } else {
            // 否则,删除记录
            followService.remove(query);
        }
        // 同步数据到行为微服务
        FollowBehaviorDto followBehaviorDto = new FollowBehaviorDto();
        followBehaviorDto.setUserId(user.getUserId());
        followBehaviorDto.setFollowId(dto.getAuthorId());
        followBehaviorDto.setEquipmentId(dto.getEquipmentId());
        followBehaviorDto.setOperation(dto.getOperation());
        String msg = JSON.toJSONString(followBehaviorDto);
        kafkaTemplate.send(followBehaviorTopic, msg);
        return ResponseResult.okResult();
    }

}
